package automate

import (
	"github.com/gin-gonic/gin"
	"github.com/gogap/logs"
	"strings"
	"yundian/internel/app/dao"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/logic"
	"yundian/internel/app/models/automate"
	"yundian/internel/app/models/paysetting"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	. "yundian/internel/pkg/dingo/result"
)

func HandleGetAutomatePdPassword(c *gin.Context) {
	userId, err := helper.GetUserIdFromCtx(c)
	dingo.ErrorIf(err).Unwrap()

	param := &request.GetAutomatePdPasswordReq{}
	dingo.ErrorIf(c.Bind(param)).Unwrap()
	param.LoginUserId = userId

	pwd := logic.NewDeviceLogic().HandleGetAutomatePasswordReplenish(param.DeviceSn, 1440)

	Response(c)("", CodeSuccess, map[string]interface{}{
		"password": pwd,
	})(OK)
	return
}

func HandleGetAutomateOrdersDetails(c *gin.Context) {
	userId, err := helper.GetUserIdFromCtx(c)
	dingo.ErrorIf(err).Unwrap()

	param := &request.GetStaffAutomateOrdersDetailsReq{}
	dingo.ErrorIf(c.Bind(param)).Unwrap()
	param.LoginUserId = userId

	data := dao.NewAutomateDaoDao().GetStaffAutomateOrdersDetails(param)
	Response(c)("", CodeSuccess, map[string]interface{}{
		"data": data.Unwrap(),
		"host": global.Cfg.Ali.AliossPath,
	})(OK)
	return
}

func HandleGetPlaceGoodsInventoryWarningList(ctx *gin.Context) {
	param := &request.GetAutomateGoodsListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	var placeIds []int
	param.WarningOrder = helper.TypeNumPlaceStatusYes
	data := dao.NewAutomateDaoDao().GetPlaceGoodsList(param)
	lists := data.Unwrap().([]*request.GetAutomatePlaceGoodsListRes)
	for _, item := range lists {
		placeIds = append(placeIds, item.PlaceId)
	}

	var resultList []*request.GetAutomatePlaceGoodsNumListRes
	logNumLists := dao.NewAutomateDaoDao().GetPlaceGoodsInventoryLogList(placeIds).Unwrap().([]*request.GetAutomatePlaceGoodsNumRes)
	orderNumLists := dao.NewAutomateDaoDao().GetPlaceGoodsOrderNumList(placeIds).Unwrap().([]*request.GetAutomatePlaceGoodsNumRes)
	deviceNumLists := dao.NewAutomateDaoDao().GetPlaceGoodsDeviceNumList(placeIds).Unwrap().([]*request.GetAutomatePlaceGoodsNumRes)
	for _, item := range lists {
		target := &request.GetAutomatePlaceGoodsNumListRes{
			GoodsId:      item.AutomateGoodsId,
			WarningNum:   item.WarningNum,
			PlaceName:    item.PlaceName,
			PlaceId:      item.PlaceId,
			GoodsName:    item.Name,
			InventoryNum: item.Num,
		}
		for _, nItem := range logNumLists {
			if item.PlaceId == nItem.PlaceId && item.AutomateGoodsId == nItem.GoodsId {
				target.ShipmentsNum = nItem.Num
				break
			}
		}
		for _, nItem := range orderNumLists {
			if item.PlaceId == nItem.PlaceId && item.AutomateGoodsId == nItem.GoodsId {
				target.SellNum = nItem.Num
				break
			}
		}
		for _, nItem := range deviceNumLists {
			if item.PlaceId == nItem.PlaceId && item.AutomateGoodsId == nItem.GoodsId {
				target.DeviceNum = nItem.Num
				target.LoadNum = nItem.LoadNum
				break
			}
		}
		resultList = append(resultList, target)
	}

	Response(ctx)("", CodeSuccess, ResponseConfigList{
		Host:       global.Cfg.Ali.AliossPath,
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       resultList,
	})(OK)
}

func HandleGetInventoryLogList(ctx *gin.Context) {
	param := &request.GetAutomateInventoryLogListListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	data := dao.NewAutomateDaoDao().GetInventoryLogList(param)
	lists := data.Unwrap().([]*request.GetAutomateInventoryLogListListRes)

	Response(ctx)("", CodeSuccess, ResponseConfigList{
		Host:       global.Cfg.Ali.AliossPath,
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       lists,
	})(OK)
}

func HandleSetInventoryPlaceGoodsNum(ctx *gin.Context) {
	dbParam := &automate.PlaceGoodsBindDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.PlaceGoodsReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	goodsInfo := dao.NewAutomateDaoDao().GetAutomateGoodsInfoById(param.Db.AutomateGoodsId).Unwrap().(*request.GetAutomateGoodsListRes)
	if goodsInfo.Num < param.Db.Num {
		Response(ctx)("运营库存不足", CodeInvalidParam, nil)(OK)
		return
	}

	if data := dao.NewAutomateDaoDao().SetPlaceGoodsInventoryNum(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	// 库存记录
	if logData := dao.NewAutomateDaoDao().InsertPlaceGoodsInventoryLog(param); logData.Err != nil {
		logs.Error("HandleInsertPlaceGoods->InsertPlaceGoodsInventoryLog", logData.Err)
	}

	// 运营库存记录
	if param.Db.Num > 0 {
		param.Db.Num = -param.Db.Num
		if logData := dao.NewAutomateDaoDao().SetAllGoodsInventoryNum(param); logData.Err != nil {
			logs.Error("HandleInsertPlaceGoods->SetAllGoodsInventoryNum", logData.Err)
		}
		if logData := dao.NewAutomateDaoDao().InsertAllGoodsInventoryLog(param); logData.Err != nil {
			logs.Error("HandleInsertPlaceGoods->InsertAllGoodsInventoryLog", logData.Err)
		}
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleDeletePlaceGoods(ctx *gin.Context) {
	dbParam := &automate.PlaceGoodsBindDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.PlaceGoodsReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	if data := dao.NewAutomateDaoDao().DeletePlaceGoods(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleUpdatePlaceGoods(ctx *gin.Context) {
	dbParam := &automate.PlaceGoodsBindDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.PlaceGoodsReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	if data := dao.NewAutomateDaoDao().UpdatePlaceGoods(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleInsertPlaceGoods(ctx *gin.Context) {
	dbParam := &automate.PlaceGoodsBindDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.PlaceGoodsReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	goodsInfo := dao.NewAutomateDaoDao().GetAutomateGoodsInfoById(param.Db.AutomateGoodsId).Unwrap().(*request.GetAutomateGoodsListRes)
	if goodsInfo.Num < param.Db.Num {
		Response(ctx)("运营库存不足", CodeInvalidParam, nil)(OK)
		return
	}

	if data := dao.NewAutomateDaoDao().InsertPlaceGoods(param); data.Err != nil {
		if strings.Index(data.Err.Error(), "Duplicate entry") > -1 {
			Response(ctx)("重复配置", CodeError, nil)(OK)
		} else {
			Response(ctx)("", CodeInternalServerError, nil)(OK)
		}
		return
	}

	// 门店库存记录
	if logData := dao.NewAutomateDaoDao().InsertPlaceGoodsInventoryLog(param); logData.Err != nil {
		logs.Error("HandleInsertPlaceGoods->InsertPlaceGoodsInventoryLog", logData.Err)
	}

	// 运营库存记录
	param.Db.Num = -param.Db.Num
	if logData := dao.NewAutomateDaoDao().SetAllGoodsInventoryNum(param); logData.Err != nil {
		logs.Error("HandleInsertPlaceGoods->SetAllGoodsInventoryNum", logData.Err)
	}
	if logData := dao.NewAutomateDaoDao().InsertAllGoodsInventoryLog(param); logData.Err != nil {
		logs.Error("HandleInsertPlaceGoods->InsertAllGoodsInventoryLog", logData.Err)
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleGetPlaceGoodsList(ctx *gin.Context) {
	param := &request.GetAutomateGoodsListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	data := dao.NewAutomateDaoDao().GetPlaceGoodsList(param)
	lists := data.Unwrap().([]*request.GetAutomatePlaceGoodsListRes)

	Response(ctx)("", CodeSuccess, ResponseConfigList{
		Host:       global.Cfg.Ali.AliossPath,
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       lists,
	})(OK)
}

func HandleGetAutomateDividendsList(ctx *gin.Context) {
	param := &request.GetAutomateDividendsListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	data := dao.NewAutomateDaoDao().GetAutomateDividendsList(param.TradeNo)

	Response(ctx)("", CodeSuccess, data.Unwrap())(OK)
}

func HandleCancelAutomateOrders(ctx *gin.Context) {
	param := &request.GetAutomateOrderListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)

	if param.IsAdmin != helper.TypeNumIsAdminOperator && param.IsAdmin != helper.TypeNumIsAdminStaff {
		return
	}

	data := dao.NewAutomateDaoDao().GetAdminAutomateOrderInfoByTradeNo(param.TradeNo).Unwrap().(*automate.OrderModel)
	if data.Id <= 0 {
		Response(ctx)("", CodeInvalidParam, false)(OK)
		return
	}

	if err := logic.NewOrderLogic().HandleWxStewardCancelOrder(&paysetting.WxStewardCancelOrder{PathKey: "automate",
		TransactionId: data.ThirdTradeNo, TradeNo: data.TradeNo, Amount: int64(data.Amount)}); err != nil {
		Response(ctx)("", CodeInternalServerError, false)(OK)
		return
	}

	updateDb := &automate.OrderPayDb{
		OrderDb: automate.OrderDb{TradeNo: data.TradeNo, Status: helper.TypeNumOrderAutomateStatusWaitRefund},
	}
	if dao.NewAutomateDaoDao().UpdateGoodsOrder(updateDb).Err != nil {
		Response(ctx)("", CodeInternalServerError, false)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleGetAutomateOrderList(ctx *gin.Context) {
	param := &request.GetAutomateOrderListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	if param.IsAdmin == helper.TypeNumIsAdminStaff {
		param.LoginUserId = 2
	}
	data := dao.NewAutomateDaoDao().GetAdminAutomateOrderList(param)
	lists := data.Unwrap().([]*automate.OrderModel)

	Response(ctx)("", CodeSuccess, ResponseConfigList{
		Host:       global.Cfg.Ali.AliossPath,
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       lists,
	})(OK)
}

func HandleDeleteGoodsBind(ctx *gin.Context) {
	dbParam := &automate.GoodsBindDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.InitGoodsBindReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	if data := dao.NewAutomateDaoDao().DeleteGoodsBind(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleUpdateGoodsBind(ctx *gin.Context) {
	dbParam := &automate.GoodsBindDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.InitGoodsBindReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	if data := dao.NewAutomateDaoDao().UpdateGoodsBind(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleInsertGoodsBind(ctx *gin.Context) {
	var dbParam []*automate.GoodsBindDb
	dingo.ErrorIf(ctx.ShouldBindJSON(&dbParam)).Unwrap()

	param := &request.InsertGoodsBindReq{DbList: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	for _, item := range dbParam {
		d := &request.InitGoodsBindReq{Db: item}
		if data := dao.NewAutomateDaoDao().InsertGoodsBind(d); data.Err != nil {
			Response(ctx)("", CodeInternalServerError, nil)(OK)
			return
		}
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleUpdateAutomateGoodsBindStatus(ctx *gin.Context) {
	dbParam := &automate.GoodsBindDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.InitGoodsBindReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	if data := dao.NewAutomateDaoDao().UpdateGoodsBindStatus(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	// 商户完成补货、同步更新工单状态
	if param.Db.Status == helper.TypeNumPlaceStatusYes {
		if nData := dao.NewNotificationDaoDao().SetNotificationServiceDoneByAutomateGoodsBindId(param.Db.Id); nData.Err != nil {
			logs.Error("SetNotificationServiceDoneByAutomateGoodsBindId", nData.Err)
		}
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleGetAutomateGoodsBindListByUserIdInApp(ctx *gin.Context) {
	param := &request.GetAutomateGoodsBindListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	data := dao.NewAutomateDaoDao().GetAutomateGoodsBindList(param)
	deviceData := dao.NewDeviceDao().GetDeviceByDeviceSn(param.DeviceSn)

	Response(ctx)("", CodeSuccess, map[string]interface{}{
		"data":       data.Unwrap(),
		"deviceInfo": deviceData.Unwrap(),
	})(OK)
}

func HandleGetAutomateGoodsBindList(ctx *gin.Context) {
	param := &request.GetAutomateGoodsBindListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	data := dao.NewAutomateDaoDao().GetAutomateGoodsBindList(param)
	lists := data.Unwrap().([]*request.GetAutomateGoodsBindListRes)

	Response(ctx)("", CodeSuccess, ResponseConfigList{
		Host:       global.Cfg.Ali.AliossPath,
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       lists,
	})(OK)
}

func HandleDeleteGoods(ctx *gin.Context) {
	dbParam := &automate.GoodsDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.InitGoodsReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	countData := dao.NewAutomateDaoDao().GetGoodsBindCount(param)
	if countData.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}
	if countData.Unwrap().(int64) > 0 {
		Response(ctx)("商品己绑定设备，请解绑后重试", CodeInvalidParam, nil)(OK)
		return
	}

	if data := dao.NewAutomateDaoDao().DeleteGoods(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleUpdateGoods(ctx *gin.Context) {
	dbParam := &automate.GoodsDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.InitGoodsReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	if data := dao.NewAutomateDaoDao().UpdateGoods(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleInitGoods(ctx *gin.Context) {
	dbParam := &automate.GoodsDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(dbParam)).Unwrap()

	param := &request.InitGoodsReq{Db: dbParam}
	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	if data := dao.NewAutomateDaoDao().InsertGoods(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandleGetAutomateGoodsList(ctx *gin.Context) {
	param := &request.GetAutomateGoodsListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.LoginUserId, _ = helper.GetUserIdFromCtx(ctx)
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	data := dao.NewAutomateDaoDao().GetAutomateGoodsList(param)
	lists := data.Unwrap().([]*request.GetAutomateGoodsListRes)

	Response(ctx)("", CodeSuccess, ResponseConfigList{
		Host:       global.Cfg.Ali.AliossPath,
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       lists,
	})(OK)
}
